/***************************************************************************
 * 
 * Copyright (c) 2011 Baidu.com, Inc. All Rights Reserved
 * 
 **************************************************************************/
 
 
 
/**
 * @file strategy_engine.cpp
 * @author liutao08(com@baidu.com)
 * @date 2011/12/18 12:39:43
 * @brief 
 *  
 **/
#include "strategy_engine.h"

StrategyEngine::~StrategyEngine()
{
    for(size_t i = 0; i < m_strategies.size(); ++i)
    {   
        delete m_strategies[i];
        m_strategies[i] = NULL;
    }   
    m_strategies.clear();
    std::map<std::string, StrategyInfo*>::iterator iter = m_StrateInfoMap.begin();
    while(iter != m_StrateInfoMap.end())
    {  
        PluginHelper::Unload(iter->second->GetHandle());
        delete iter->second;
        iter->second = NULL;
        ++iter;
    }   
    m_StrateInfoMap.clear();
}

bool StrategyEngine::Init(CommunicationManager* cManager, xmlNodePtr strategyNode)
{
    std::string strategyName = ""; 
    std::string soName = ""; 
    std::string confName = ""; 
    bool isOff = false;
    xmlChar* stAttr = NULL;
    for(strategyNode = strategyNode->xmlChildrenNode; strategyNode != NULL; strategyNode = strategyNode->next)
    {   
        strategyName = ""; 
        soName = ""; 
        confName = ""; 
        isOff = false; 
        stAttr = NULL;
        if (xmlStrcmp(strategyNode->name,  BAD_CAST "strategy"))
        {   
            WARNING("This phase has no strategy! [%s]", strategyNode->name);
            continue;
        }   
        stAttr = xmlGetProp(strategyNode, BAD_CAST "switch");
        if(stAttr != NULL && !xmlStrcmp(stAttr,  BAD_CAST "off"))
        {   
            isOff = true;
            xmlFree(stAttr);
        }   
        if(isOff)
            continue;
        stAttr = xmlGetProp(strategyNode, BAD_CAST "class");
        if(NULL == stAttr)
        {
            WARNING("document of the wrong type, strategyNode name is null!");
            continue;
        }
        strategyName = reinterpret_cast<char *>(stAttr);
        xmlFree(stAttr);
        stAttr = xmlGetProp(strategyNode, BAD_CAST "so");
        if(NULL == stAttr)
        {
            WARNING("document of the wrong type, strategyNode soNname is null!");
            continue;
        }
        soName = reinterpret_cast<char *>(stAttr);
        xmlFree(stAttr);
        StrategyInfo* stInfo = new(std::nothrow)StrategyInfo();
        if(NULL == stInfo)
        {
            FATAL("malloc StrategyInfo is fail!");
            return false;
        }
        stInfo->name = strategyName;
        stInfo->soName = soName;
        if(!InitConfig(stInfo, strategyNode))
        {
            FATAL("Strategy[%s] InitConfig is fail!", strategyName.c_str());
            return false;
        }
        void* handle = PluginHelper::Load(soName);
        if (handle == NULL)
        {
            FATAL("load so library %s fail.", soName.c_str());
            return false;
        }
        stInfo->SetHandle(handle);
        CreateStrategy_T createFactory = (CreateStrategy_T)(PluginHelper::GetCreatePoint(stInfo->name, \
                                          CREATE_STRATEGY_PREFIX, handle));
//        stInfo->createFactory = (CreateStrategy_T)(PluginHelper::GetCreatePoint(stInfo->name, \
                                 CREATE_STRATEGY_PREFIX, handle));
        m_StrateInfoMap[stInfo->name] = stInfo;
        Strategy* st = createFactory();
        if(NULL == st)
        {
            FATAL("Creat strategy [%s] is fail!", stInfo->name.c_str());
            return false;
        }
        if(!st->Init(*stInfo, cManager))
        {
            FATAL("Init strategy [%s] is fail!", stInfo->name.c_str());
            return false;
        }
        m_strategies.push_back(st);
    }
    return true;
}

bool StrategyEngine::Run(CommunicationManager* cManager)
{
    for(size_t i = 0; i < m_strategies.size(); ++i)
    {
        if (!m_strategies[i]->Run(cManager))
        {
            return false;
        }
    }
    return true;
}

void StrategyEngine::ResetStrategys(CommunicationManager* cManager)
{
    for(size_t i = 0; i < m_strategies.size(); ++i)
    {
        m_strategies[i]->Reset(cManager);
    }
}

StrategyInfo* StrategyEngine::GetStrategyInfo(const std::string& name)
{
     std::map<std::string, StrategyInfo*>::iterator iter = m_StrateInfoMap.find(name);
     if(iter == m_StrateInfoMap.end())
         return NULL;
     return iter->second;
}

bool StrategyEngine::InitConfig(StrategyInfo* strategyInfo, xmlNodePtr configNode)
{
    xmlChar* reAttr = NULL;
    std::string key = ""; 
    std::string value = ""; 
    for(configNode = configNode->xmlChildrenNode; configNode != NULL; configNode = configNode->next)
    {   
        if(xmlStrcmp(configNode->name,  BAD_CAST "config"))
        {   
            WARNING("This strategy has no config! name[%s]", strategyInfo->name.c_str());
            continue;
        }   
        reAttr = xmlGetProp(configNode, BAD_CAST "name");
        if(NULL == reAttr)
        {   
            WARNING("strategy[%s] config name is null!", strategyInfo->name.c_str());
            return false;
        }   
        key = reinterpret_cast<char *>(reAttr);
        xmlFree(reAttr);
        reAttr = xmlGetProp(configNode, BAD_CAST "value");
        if(NULL == reAttr)
        {   
            WARNING("strategy[%s] config value is null!", strategyInfo->name.c_str());
            return false;
        }   
        value = reinterpret_cast<char *>(reAttr);
        xmlFree(reAttr);
        if(strategyInfo->InsertConfig(key, value) < 0)
        {   
            WARNING("InsertConfig is fail! key[%s]", key.c_str());
            return false;
        } 
    }   
    return true;
}













/* vim: set expandtab ts=4 sw=4 sts=4 tw=100: */
